﻿using System.Linq;
using CID.Domain.Operations;
using CID.Tests.Support;
using NUnit.Framework;

namespace CID.Domain.Persistence.Tests.Operations
{
    [TestFixture]
    class EnvironmentPersistenceTests : BasePersistenceWithDataTests
    {
        private static void AssertAreEqual(Environment expected, Environment actual)
        {
            Assert.AreEqual(expected.Id, actual.Id);
            Assert.AreEqual(expected.Name, actual.Name);
            Assert.AreEqual(expected.Description, actual.Description);
            Assert.AreEqual(expected.Responsible.Id, actual.Responsible.Id);
            Assert.AreEqual(expected.Enabled, actual.Enabled);
            Assert.AreEqual(expected.IsProduction, actual.IsProduction);
            CollectionAssert.AreEquivalent(expected.Assignments.Select(x => x.Id), actual.Assignments.Select(x => x.Id));
            CollectionAssert.AreEquivalent(expected.ActiveVersions.Select(x => x.Id), actual.ActiveVersions.Select(x => x.Id));
        }

        [Test]
        public void SaveNewEnvironment_EnvironmentShouldBeSaved()
        {
            var session = OpenSession();
            var newEnvironment = DataProvider.CreateEnvironment(session, UsersData.User1);
            session.SaveOrUpdate(newEnvironment);
            CleanSession(session);

            Assert.AreNotEqual(NotSavedId, newEnvironment.Id);
            session = OpenSession();
            var retrievedEnvironment = session.Get<Environment>(newEnvironment.Id);
            AssertAreEqual(newEnvironment, retrievedEnvironment);
            CleanSession(session);
        }

        [Test]
        public void SaveModifiedEnvironment_ChangesShouldBeSaved()
        {
            var session = OpenSession();
            var newEnvironment = DataProvider.CreateEnvironment(session, UsersData.User1);
            session.SaveOrUpdate(newEnvironment);
            CleanSession(session);

            session = OpenSession();
            var modifiedEnvironment = session.Get<Environment>(newEnvironment.Id);
            AssertAreEqual(newEnvironment, modifiedEnvironment); //Necessary to load lazy collections before the session is wiped out
            modifiedEnvironment.ModifyProperty(x => x.Name);
            modifiedEnvironment.ModifyProperty(x => x.Description);
            modifiedEnvironment.ModifyProperty(x => x.Enabled);
            modifiedEnvironment.ModifyProperty(x => x.IsProduction);
            var serverRole = DataProvider.GetServerRole(session, OperationsData.ServerRole1);
            var server = DataProvider.GetServer(session, OperationsData.Server1);
            server.Assign(modifiedEnvironment, serverRole);
            session.SaveOrUpdate(modifiedEnvironment);
            CleanSession(session);

            session = OpenSession();
            var retrievedEnvironment = session.Get<Environment>(newEnvironment.Id);
            AssertAreEqual(modifiedEnvironment, retrievedEnvironment);
            CleanSession(session);
        }

        [Test]
        public void DeleteEnvironment_EnvironmentShouldBeDeleted()
        {
            var session = OpenSession();
            var newEnvironment1 = DataProvider.CreateEnvironment(session, UsersData.User1, "Another environment name");
            var newEnvironment2 = DataProvider.CreateEnvironment(session, UsersData.User2);
            session.SaveOrUpdate(newEnvironment1);
            session.SaveOrUpdate(newEnvironment2);
            CleanSession(session);

            session = OpenSession();
            var retrievedEnvironment1 = session.Get<Environment>(newEnvironment1.Id);
            session.Delete(retrievedEnvironment1);
            CleanSession(session);

            session = OpenSession();
            retrievedEnvironment1 = session.Get<Environment>(newEnvironment1.Id);
            var retrievedEnvironment2 = session.Get<Environment>(newEnvironment2.Id);
            Assert.IsNull(retrievedEnvironment1);
            Assert.IsNotNull(retrievedEnvironment2);
            CleanSession(session);
        }

        [Test]
        public void RegisterReleaseDeploymentInEnvironment_ActiveVersionsShouldBeSaved()
        {
            var session = OpenSession();
            var newEnvironment = DataProvider.CreateEnvironment(session, UsersData.User1);
            newEnvironment.RegisterReleaseDeployment(Development.DataProvider.GetRelease(session, DevelopmentData.Release1));
            session.SaveOrUpdate(newEnvironment);
            CleanSession(session);

            session = OpenSession();
            var retrievedEnvironment = session.Get<Environment>(newEnvironment.Id);
            AssertAreEqual(newEnvironment, retrievedEnvironment);
            CollectionAssert.IsNotEmpty(retrievedEnvironment.ActiveVersions);
            CleanSession(session);
        }

        [Test]
        public void RegisterDoubleReleaseDeploymentInEnvironment_ActiveVersionsShouldBeUpdated()
        {
            var session = OpenSession();
            var newEnvironment = DataProvider.CreateEnvironment(session, UsersData.User1);
            newEnvironment.RegisterReleaseDeployment(Development.DataProvider.GetRelease(session, DevelopmentData.Release1));
            session.SaveOrUpdate(newEnvironment);
            CleanSession(session);


            session = OpenSession();
            var modifiedEnvironment = session.Get<Environment>(newEnvironment.Id);
            AssertAreEqual(newEnvironment, modifiedEnvironment); //Necessary to load lazy collections before the session is wiped out
            modifiedEnvironment.RegisterReleaseDeployment(Development.DataProvider.GetRelease(session, DevelopmentData.Release2));
            modifiedEnvironment.UnregisterComponentDeployed(Development.DataProvider.GetComponent(session, DevelopmentData.Component1));
            session.SaveOrUpdate(modifiedEnvironment);
            CleanSession(session);

            session = OpenSession();
            var retrievedEnvironment = session.Get<Environment>(newEnvironment.Id);
            AssertAreEqual(modifiedEnvironment, retrievedEnvironment);
            CleanSession(session);
        }
    }
}
